home *** CD-ROM | disk | FTP | other *** search
- // Copyright (c) 1994, University of Kansas, All Rights Reserved
- //
- // Class: TURLView
- // Include File: turlview.h
- // Purpose: Provide a view for an HTML document.
- // Remarks/Portability/Dependencies/Restrictions:
- // These functions in effect take the place of the original
- // gridtext functions and provide a multiple document interface
- // since each view will have its own rendered copy of the
- // original HTML image.
- // All functions are here in the same file since all will be
- // called at once. No need to split up to help overlay manager.
- // The collection TNSCp_lines is used to hold the offset of
- // all inserted lines in the collection.
- // Revision History:
- // 02-15-94 created
- // 02-18-94 Possible cause for heap corruption adjusted,
- // incorrect pointer addition.
- // This only corrected rendered output, heap
- // corruption still occuring.
- // 02-18-94 Changed appendCharacter to accept a
- // character instead of an signed short int.
- // Changes split_line to reset the line
- // split value each time it is called.
- // No more corrupt heaps it seems.
- // 02-18-94 Experiencing crashes after a large number
- // of lines are processed, no apparent reason.
- // Optimizing the code, it is very slow....
- // 02-21-94 Beginning to see increase in speed due to
- // minimizing the number of function calls made.
- // Crashes resulting due to large number of
- // lines seem to be avoided by increasing the
- // delta argument in the TNSCollection
- // constructor (see TURLView constructor).
- // 02-22-94 Added member to class, B_avoidinfinite, to
- // avoid infinite loops in the Double font and
- // appendCharacter.
- // 02-25-94 Modified to work with no HText styles,
- // anchors, or paragraphs in memory.
- // Always assuming that a style is active for
- // speed.
- #define Uses_TProgram
- #define Uses_TKeys
- #include"turlview.h"
- #include"tcapture.h"
- #include"trace.h"
- #include<string.h>
-
- extern "C" {
- #include"htfont.h"
- };
-
- void TURLView::FormatHTML() {
- // Purpose: Format the HTML image file produced in gridtext.cpp
- // into a rendered document fit for display in a view.
- // Arguments: void
- // Return Value: void
- // Remarks/Portability/Dependencies/Restrictions:
- // Using indexOf on the HText paragraph collection is fatal
- // for some reason. Using the member of TextAttribute to find
- // the index.
- // Revision History:
- // 02-15-94 created
- // 02-25-94 modified so will not read HText image file
- // with anchors, sytles, paragraphs in memory.
- // 04-06-94 Modified to compensate for WWW not calling
- // HText_endAppend.
- #ifndef RELEASE
- trace("Entering FormatHTML.");
- #endif // RELEASE
- // In certain cases, the WWW library does not call
- // HText_endAppend. Do this for them. We can tell if the image
- // file still exists.
- if(HTp_HyperDoc->fsp_image != NULL) {
- #ifndef RELEASE
- trace("WWW did not call HText_endAppend. Doing so now.");
- #endif // RELEASE
- ::HText_endAppend(HTp_HyperDoc);
- }
-
- // Open the HTML image file for reading.
- fsp_image = new fstream(HTp_HyperDoc->TTNp_fspname->
- getName(), ios::in | ios::nocreate | ios::binary);
- if(fsp_image == NULL) {
- doslynxmessage("Unable to open HText image file " <<
- HTp_HyperDoc->TTNp_fspname->getName());
- B_valid = False;
- return;
- }
-
- // Open the view's temporary rendered file for writing.
- fsp_temp = new fstream(TTNp_temp->getName(), ios::out | ios::trunc |
- ios::binary);
- if(fsp_temp == NULL) {
- doslynxmessage("Unable to open HTML rendering file " <<
- TTNp_temp->getName());
- // Close the HTML image file.
- fsp_image->close();
- delete(fsp_image);
- B_valid = False;
- return;
- }
-
- // Allocate the two lines with the appropriate screen size and
- // a safety buffer.
- L_last = (Line *)new char[sizeof(Line) + size.x + 80];
- L_new = (Line *)new char[sizeof(Line) + size.x + 80];
-
- if(L_last == NULL || L_new == NULL) {
- doslynxmessage("Unable to allocate enough memory to create.");
- // Close the files.
- fsp_image->close();
- fsp_temp->close();
- delete(fsp_image);
- delete(fsp_temp);
- B_valid = False;
- if(L_last != NULL) {
- delete[](L_last);
- }
- if(L_new != NULL) {
- delete[](L_new);
- }
- return;
- }
- L_last->ssi_indent = 0;
- L_last->ssi_length = 0;
-
- // We are in a new paragraph and can't split anywhere.
- B_line_1 = True;
- ssi_splitAt = 0;
-
- // Right now, there are no limits to the view.
- limit.y = limit.x = 0;
-
- // Set member to avoid infinite loop in appendcharacter and
- // the double font.
- B_avoidinfinite = False;
-
- // There have been no spaces, but start out if so.
- B_lastSpace = True;
- // Right now we will collapse spaces.
- B_collapseSpaces = True;
-
- // No current style
- HTSp_style = NULL;
-
- // If there were anchors skipped, report it.
- if(usi_skipped != 0U) {
- doslynxmessage(usi_skipped << " anchors not created due to "
- "memory limitations.");
- usi_skipped = 0U;
- }
-
- // Go through the HTML image file, calling the appropriate
- // rendering functions for the temporary rendered file.
- char c_append;
- unsigned short int usi_checkEsc = 0;
- signed long int sli_tellg = fsp_image->tellg();
- while(fsp_image->eof() == 0) {
- // Get a character and act upon it.
- // Update where we are in the file.
- c_append = fsp_image->get();
- sli_tellg++;
- if(c_append == EOF || fsp_image->bad() != 0) {
- break;
- }
- // Check for embedded characters.
- else if(c_append == c_Embedded) {
- // Is an embedded character, get the next one
- // that tells us what type of embed it is.
- c_append = fsp_image->get();
- sli_tellg++;
- if(c_append == EOF || fsp_image->bad() != 0) {
- break;
- }
- // Check for styles.
- else if(c_append == c_SetStyle) {
-
- auto HTStyle *HTSp_nextStyle;
-
- // Changing the current style.
- // Get the style pointer from the file.
- fsp_image->read((char *)(&HTSp_nextStyle),
- sizeof(HTStyle *));
- sli_tellg += sizeof(HTStyle *);
- if(fsp_image->gcount() != sizeof(HTStyle *) ||
- fsp_image->bad() != 0) {
- break;
- }
-
- // If there was a previous style, insert
- // blank lines.
- if(HTSp_style != NULL) {
- blank_lines(max(HTSp_style->
- spaceAfter,
- HTSp_nextStyle->spaceBefore));
- }
-
- // Change to the current style.
- HTSp_style = HTSp_nextStyle;
-
- // Set wether or not to collapse spaces.
- // Will do so whenever style is not
- // preformatted or an example.
- if(HTSp_style != NULL) {
- #ifndef RELEASE
- trace("Current style is now " <<
- HTSp_style->name);
- #endif // RELEASE
- if(!strcmp(HTSp_style->name,
- "Preformatted") ||
- !strcmp(HTSp_style->name,
- "Example")) {
- B_collapseSpaces = False;
- }
- else {
- B_collapseSpaces = True;
- }
- }
- }
- // Check for paragraph.
- else if(c_append == c_AppendParagraph) {
-
- // Assume we have a style regardless.
- blank_lines(max(HTSp_style->spaceAfter,
- HTSp_style->spaceBefore));
- }
- // Check for beginning an anchor.
- else if(c_append == c_BeginAnchor) {
- auto HTChildAnchor *HTCAp_newAnchor;
-
- // Read the value of the pointer from
- // file.
- fsp_image->read((char *)(&HTCAp_newAnchor),
- sizeof(HTChildAnchor *));
- sli_tellg += sizeof(HTChildAnchor *);
- if(fsp_image->gcount() != sizeof(
- HTChildAnchor *) ||
- fsp_image->bad() != 0) {
- break;
- }
-
- // Begin the anchor in the view.
- beginAnchor(HTCAp_newAnchor);
- }
- // Check for ending an anchor.
- else if(c_append == c_EndAnchor) {
- // Simply call end anchor.
- endAnchor();
- }
- }
- // Otherwise, should be an appendable character.
- else {
- appendCharacter(c_append);
- }
-
- // Every 1k of read information, check to see if
- // user is trying to interrupt.
- if(usi_checkEsc++ > 1024U) {
- // Reset usi_checkEsc
- usi_checkEsc = 0U;
-
- // Check if safe to coninue formatting due to
- // memory limitations. The last ??? chunks of
- // mem will cause this to break.
- if(really_safe_pool[Stop_Rendering] == NULL) {
- doslynxmessage("Unable to display full "
- "document due to memory limitations.");
- break;
- }
-
- auto TEvent TE;
-
- // Get any events in the application.
- // Calls this to also call idle.
- TProgram::application->getEvent(TE);
-
- // Interrupt on ESC key.
- if(TE.what & evKeyDown) {
- if(TE.keyDown.keyCode == kbEsc) {
- doslynxmessage("Interrupting the "
- "format process.");
- doslynxmessage("Display will not "
- "represent the full "
- "document.");
- // Clear the event.
- TProgram::application->clearEvent(TE);
- break;
- }
- }
-
- // Print a message if other events occured.
- if(TE.what != evNothing && !(TE.what & evMouseMove)
- && !(TE.what & evMouseUp)) {
- doslynxmessage("Formatting.... press ESC to "
- "interrupt.");
- }
-
- // Clear the event.
- TProgram::application->clearEvent(TE);
- }
- }
-
- if(fsp_image->bad() != 0) {
- doslynxmessage("Error while reading HText image file.");
- doslynxmessage("Displaying rendering as is.");
- }
-
- // Flush and release the lines.
- split_line(0);
- delete[]((char *)L_last);
- delete[]((char *)L_new);
-
- // Close the files.
- fsp_image->close();
- delete(fsp_image);
- fsp_temp->close();
- delete(fsp_temp);
-
- // Adjust the selected anchor to now select the anchor in
- // the rendered file.
- if(HTCAp_2BSelected != NULL) {
- adjustSelected();
- }
-
- // Tell the view what it's new bounds are.
- // This will set the scroll bar values.
- setLimit(limit.x, limit.y);
-
- #ifndef RELEASE
- trace("FormatHTML returning.");
- #endif // RELEASE
- }
-
- void TURLView::blank_lines(signed short int ssi_blanks) {
- // Purpose: Insert a number of blank lines into the rendered
- // image.
- // Arguments: ssi_blanks The number of blank lines to insert.
- // Return Value: void
- // Remarks/Portability/Dependencies/Restrictions:
- // Will not count the number of previous blank lines before
- // insertion.
- // Revision History:
- // 02-16-94 created
-
- // Insert the appropriate number of blanks.
- // Always atleast split one line.
- do {
- split_line(0);
- }
- while(--ssi_blanks > 0);
-
- B_line_1 = True;
- }
-
- void TURLView::appendCharacter(char c_append) {
- // Purpose: Append a character to the output stream.
- // Arguments: c_append The character to append.
- // Return Value: void
- // Remarks/Portability/Dependencies/Restrictions:
- // Assumes that any functions changing the actual last line
- // in the rendered image will update the last line member.
- // Revision History:
- // 02-16-94 created
- // 03-16-94 Modified to collapse spaces ' ' around all
- // types of whitespace. For prettier output.
- // Care should be taken to not call this
- // function using spaces to align or indent
- // text, or the formatting will be collapsed.
-
- // Check to see if we should ignore a space.
- if(c_append == ' ') {
- // Ignore it if need be.
- if(B_lastSpace == True && B_collapseSpaces == True) {
- return;
- }
-
- // Set for future condensing.
- B_lastSpace = True;
-
- // Can split the line here.
- ssi_splitAt = L_last->ssi_length;
- }
- else {
- // Set so next time we know we have no spaces collapsed.
- B_lastSpace = False;
- }
-
- // Determine the current indention of the line, if we have
- // style.
- auto signed short int ssi_indent = 0;
- if(B_line_1 == True) {
- ssi_indent = HTSp_style->indent1st;
- }
- else {
- ssi_indent = HTSp_style->leftIndent;
- }
-
- // Check for new lines.
- // Set whitespace here.
- if(c_append == '\n') {
- // Considered a space so that following spaces are
- // collapsed.
- B_lastSpace = True;
- split_line(0);
- B_line_1 = True;
- return;
- }
- // Check for tabs.
- // If so, consider whitespace.
- else if(c_append == '\t') {
- // Considered a space so that we collapse more spaces.
- B_lastSpace = True;
- // The tab table.
- HTTabStop *HTTSp;
- // Where to tab to.
- int i_target;
- // Where we are.
- int i_here = L_last->ssi_length + L_last->ssi_indent
- + ssi_indent;
-
- // If we have a tab table.
- if(HTSp_style->tabs != NULL) {
- // Loop through the tab table until
- // a tab will put the cursor past our
- // current postion.
- for(HTTSp = HTSp_style->tabs; HTTSp->position <=
- i_here; HTTSp++)
- {
- // No tab specified.
- if(HTTSp->position == 0) {
- split_line(0);
- return;
- }
- }
- i_target = HTTSp->position;
- }
- // No tab table, if in line 1 of a paragraph,
- // use the leftIndent.
- else if(B_line_1 == True) {
- // If already beyond the left indent.
- if(i_here >= HTSp_style->leftIndent) {
- split_line(0);
- return;
- }
- else {
- i_target = HTSp_style->leftIndent;
- }
- }
- // No tab table, not in line 1, use default mod 8
- else {
- #ifdef TABS8
- i_target = (L_last->ssi_indent + L_last->ssi_length +
- 8) % 8 + HTSp_style->leftIndent;
- #else
- // Just split the line.
- split_line(0);
- #endif // TABS8
- return;
- }
-
- // If we are past the right margin.
- if(i_target > size.x - HTSp_style->rightIndent) {
- split_line(0);
- return;
- }
- // Otherwise, indent the tab.
- else {
- // We can split the line here.
- ssi_splitAt = L_last->ssi_length;
- // If there is nothing in the line, just
- // increase the indentation.
- if(L_last->ssi_length == 0) {
- L_last->ssi_indent += i_target - i_here;
- }
- // Otherwise, space out.
- else {
- for(; i_here < i_target; i_here++) {
- *((char *)L_last + sizeof(Line) +
- L_last->ssi_length) = ' ';
- L_last->ssi_length++;
- }
- }
- return;
- }
- }
-
- // Check if beyond the screen width.
- if(ssi_indent + L_last->ssi_indent + L_last->ssi_length + HTSp_style->
- rightIndent >= size.x)
- {
- if(HTSp_style->wordWrap != 0) {
- split_line(ssi_splitAt);
- // We can ignore a space causing a split
- if(c_append == ' ') {
- return;
- }
- }
- else {
- split_line(0);
- }
- }
-
- // The font of the sytle.
- HTFont HTF = HTSp_style->font;
-
- // Convert NBS to a space.
- // Do not consider as whitespace.
- if(c_append == HT_NON_BREAK_SPACE) {
- c_append = ' ';
- }
- // Convert the character according to font.
- else if(HTF & HT_CAPITALS) {
- c_append = toupper(c_append);
- }
-
- // Add the character to the line.
- *((char *)L_last + sizeof(Line) + L_last->ssi_length) = c_append;
- L_last->ssi_length++;
-
- // On the double font, do again with a NBS
- if(HTF & HT_DOUBLE) {
- // Failsafe to not go infinitly recursive.
- if(B_avoidinfinite == False) {
- B_avoidinfinite = True;
- }
- else {
- B_avoidinfinite = False;
- }
-
- if(B_avoidinfinite == True) {
- appendCharacter(HT_NON_BREAK_SPACE);
- }
- }
- }
-
- void TURLView::split_line(signed short int ssi_split) {
- // Purpose: Split a line at the required offset.
- // Arguments: ssi_split Where to split the line.
- // If 0, no split, just a new line.
- // Return Value: void
- // Remarks/Portability/Dependencies/Restrictions:
- // Revision History:
- // 02-16-94 created
- // 02-22-98 Modified to use nothing but a TNSCollection
- // to keep track of line offsets into the
- // rendered file. No memory other than the
- // collection is allocated.
-
- // Reset where last line will be split.
- ssi_splitAt = 0;
-
- // Fill the members with pertinent data for the new line.
- L_new->ssi_indent = L_new->ssi_length = 0;
-
- // Split at required point, skip if not needed
- if(ssi_split != 0 && L_last->ssi_length != 0) {
- // End the line.
- *((char *)L_last + sizeof(Line) + L_last->ssi_length) =
- '\0';
- // Skip any space at the split point.
- char *cp;
- for(cp = (char *)L_last + sizeof(Line) + ssi_split; *cp !=
- '\0'; cp++) {
- if(*cp != ' ') {
- break;
- }
- }
- // Copy the remaining information into the new line and
- // set the members.
- strcpy(((char *)L_new + sizeof(Line)), cp);
- L_new->ssi_length = strlen(((char *)L_new + sizeof(Line)));
- L_last->ssi_length = ssi_split;
- }
-
- // Take off any trailing spaces.
- while(L_last->ssi_length != 0 && *((char *)L_last + sizeof(Line) +
- L_last->ssi_length) == ' ' - 1) {
- L_last->ssi_length--;
- }
-
- // End the line.
- if(L_last->ssi_length != 0) {
- *((char *)L_last + sizeof(Line) + L_last->ssi_length) =
- '\0';
- }
-
- // Align the line according to style.
- auto int i_indent = (B_line_1 == True) ? HTSp_style->indent1st :
- HTSp_style->leftIndent;
- auto int i_spare = size.x - HTSp_style->rightIndent +
- HTSp_style->leftIndent - L_last->ssi_length;
-
- switch(HTSp_style->alignment) {
- case HT_CENTER:
- L_last->ssi_indent += i_indent + i_spare / 2;
- break;
- case HT_RIGHT:
- L_last->ssi_indent += i_indent + i_spare;
- break;
- default:
- L_last->ssi_indent += i_indent;
- break;
- }
-
- // We are no longer in the first line of a paragraph unless
- // the calling function sets this otherwise.
- B_line_1 = False;
-
- // Set the line collection to know where the offset of the
- // line to be serialized is. Using only an offset to track.
- // Using the offset as a void * to track.
- TNSCp_lines->insert((void *)(fsp_temp->tellp()));
-
- // Write the line to the rendered image file.
- fsp_temp->write((const char *)L_last, sizeof(Line) + L_last->
- ssi_length);
- // Check for error in write, if so, must unfortunately exit.
- if(fsp_temp->bad() != 0) {
- doslynxmessage("Error in creating rendered image.");
-
- // Attemp closing the files.
- fsp_temp->close();
- fsp_image->close();
-
- // Cause the application to quit.
- TEvent TE_quit;
- TE_quit.what = evMessage;
- TE_quit.message.command = cmQuit;
- TProgram::application->handleEvent(TE_quit);
- }
-
- // Increment the total number of lines and maximum width.
- limit.y++;
- limit.x = max(limit.x, L_last->ssi_length + L_last->ssi_indent);
-
- // We have a new last line.
- Line *L_temp = L_last;
- L_last = L_new;
- L_new = L_temp;
- }
-
- void TURLView::beginAnchor(const HTChildAnchor *HTCAp_anchor) {
- // Purpose: Mark the beginning of an anchor in the rendered image.
- // Arguments: HTCAp_anchor The child anchor to begin.
- // Return Value: void
- // Remarks/Portability/Dependencies/Restrictions:
- // Creates a new anchor entry with offsets in the rendered file
- // pointing to the corresponding current anchor.
- // Revision History:
- // 02-17-94 created
-
- // Create a new anchor.
- TextAttribute *TAp_newanc = new TextAttribute(HTCAp_anchor);
- if(TAp_newanc == NULL) {
- doslynxmessage("Unable to allocate space for new anchor.");
- B_valid = False;
- return;
- }
-
- // Get the offset of the last line and it's offset by length
- // and structure size.
- signed long int sli_where = fsp_temp->tellp() + (signed long int)
- (L_last->ssi_length + sizeof(Line));
-
- // Set the beginning offset in the rendering.
- TAp_newanc->Begin(sli_where);
-
- // Insert the anchor into the anchor collection.
- TNSCp_anchors->insert((void *)TAp_newanc);
- }
-
- void TURLView::endAnchor() {
- // Purpose: End an anchor in the rendered image.
- // Arguments: void
- // Return Value: void
- // Remarks/Portability/Dependencies/Restrictions:
- // Ends the last anchor in the collection at the current
- // length of the last line in the offset of the rendering.
- // Revision History:
- // 02-17-94 created
-
- // Get the last anchor. Assume there is always one.
- TextAttribute *TAp_anclast = (TextAttribute *)(TNSCp_anchors->at(
- TNSCp_anchors->getCount() - 1));
-
- // Get the offset of the last line and it's offset by length
- // and structure size.
- signed long int sli_where = fsp_temp->tellp() + (signed long int)
- (L_last->ssi_length + sizeof(Line));
-
- // Set the ending offset in the rendering.
- TAp_anclast->End(sli_where);
- }
-
- void TURLView::adjustSelected() {
- // Purpose: The selected anchor originally points to the anchor
- // owned by HText. Convert the pointer of that anchor
- // to the corresponding anchor owned by the view.
- // Arguments: void
- // Return Value: void
- // Remarks/Portability/Dependencies/Restrictions:
- // Revision History:
- // 02-17-94 created
-
- #ifndef RELEASE
- trace("Adjusting the selected anchor.");
- #endif // RELEASE
-
- // Find the corresponding anchor.
- // Assume that a match will always be found.
- TextAttribute *TAp_same;
- for(TAp_same = (TextAttribute *)(TNSCp_anchors->at(0));
- TAp_same->HTCAp_anchor != HTCAp_2BSelected;
- TAp_same = (TextAttribute *)(TNSCp_anchors->at(TNSCp_anchors
- ->indexOf((void *)TAp_same) + 1))) {
- // Null body
- }
-
- // Set the selected anchor.
- TAp_selected = TAp_same;
- }
-